#include <iostream>
//装饰器模式
class Worker
{
public:
    virtual void DoWork() = 0;
};

class WoodMan : public Worker
{
public:
    void DoWork() override
    {
        printf("lumbering.\n");//砍树
    }

};

class SalesMan : public Worker
{
public:
    void DoWork() override
    {
        printf("Selling.\n");//贩卖
    }
};
//被装饰的售货员和伐木工，是主体类，都可以单独存在，完成工作。


//这里继承Worker纯粹是为了接口一致，实际干活的是被修饰的主体类
class BaseWorkerDecorate : public Worker
{
protected:
    Worker* wkr;
public:
    BaseWorkerDecorate(Worker* w) :wkr(w) {}
    void Dowork()
    {
        if(wkr != nullptr)
            wkr->DoWork();
    }
};

//让工人有投票的行为
class VoterDecorate :public BaseWorkerDecorate
{
public:
    VoterDecorate(Worker* wkr) :BaseWorkerDecorate(wkr) {}
    void DoWork() override
    {
        BaseWorkerDecorate::DoWork();
        Voting();
    }
    void Voting()
    {
        printf("Voting.\n");//投票
    }
};

//让工人有罢工的行为
class StrikerDecorate :public BaseWorkerDecorate
{
public:
    StrikerDecorate(Worker* wkr) :BaseWorkerDecorate(wkr) {}
    void DoWork() override
    {
        BaseWorkerDecorate::DoWork();
        Strike();
    }
    void Strike()
    {
        printf("Walkout.\n");//罢工
    }
};

//策略模式
class Context
{
public:
    void Init()
    {
        config = 0.0f;
        result = 0;
    }
    void SetWorkingResult(int res)
    {
        result = res;
    }
    int GetWorkingResult()
    {
        return result;
    }
    void SetWorkingConfig(float cfg)
    {
        config = cfg;
    }
    float GetWorkingConfig()
    {
        return config;
    }
private:
    float config;
    int result;
};

class Strategy
{
public:
    virtual void Dowork(Context* ctx) = 0;
};

class StrategyA :public Strategy
{
public:
    void Dowork(Context* ctx) override
    {
        float cfg = ctx->GetWorkingConfig();
        if (cfg > 0.5)
            ctx->SetWorkingResult(1);
        else
            ctx->SetWorkingResult(2);
    }
};

class StrategyB :public Strategy
{
public:
    void Dowork(Context* ctx) override
    {
        float cfg = ctx->GetWorkingConfig();
        if (cfg * 100 > 10)
            ctx->SetWorkingResult(3);
        else
            ctx->SetWorkingResult(4);
    }
};

//1.只需要继承扩展装饰类，就能为Worker增加很多丰富的功能
//2.只要继续继承扩展策略类，就能为Dowork增加更多解决方案
int main(int argc, char* argv[])
{
    Worker* woder = new WoodMan();
    Worker* ameraic_woder = new VoterDecorate(woder);//美国伐木工有投票的权力
    Worker* frence_woder = new StrikerDecorate(woder);//法国伐木工有罢工的权利
    
    ameraic_woder->DoWork();//美国伐木工，砍完树然后去投票

    frence_woder->DoWork();//法国伐木工，砍完树然后去罢工
    
    delete ameraic_woder;
    delete frence_woder;
    delete woder;

    Context ctx;
    StrategyA str_a;
    ctx.SetWorkingConfig(0.9);//通过context传递执行所需的上下文环境
    str_a.Dowork(&ctx);
    int res = ctx.GetWorkingResult();
    return 0;
}
